/*  ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** 
*   Copyright 2014 Jan-Marwin Wollschläger                                   *
*                                                                            *
*   Licensed under the Apache License, Version 2.0 (the "License");          *
*   you may not use this file except in compliance with the License.         *
*   You may obtain a copy of the License at                                  *
*                                                                            *
*       http://www.apache.org/licenses/LICENSE-2.0                           *
*                                                                            *
*   Unless required by applicable law or agreed to in writing, software      *
*   distributed under the License is distributed on an "AS IS" BASIS,        *
*   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. *
*   See the License for the specific language governing permissions and      *
*   limitations under the License.                                           *
** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** **   */   

import java.util.ArrayList;

/**
 * Very important TestCase, as here the behaviour of one of the most important
 * classes is tested: the behaviour of molecules, which basically are made of
 * atoms and bonds as they are represented by the interfaces IAtom and IBond,
 * respectively. 
 * It could also be interesting to provide Molecule instances with Mock atoms
 * and bonds!
 *
 * @author Jan-Marwin Wollschläger
 * @version 0.1
 **/
class MoleculeTestCase implements ITestCase
{
  Unit unit;
  public MoleculeTestCase()
  {
    unit = new Unit(this);
  }
  
  public void testMoleculeMethods()
  {
	 /* Create empty atoms and bonds arraylist */
     final ArrayList<IAtom> atoms = new ArrayList<IAtom>();
     final ArrayList<IBond> bonds = new ArrayList<IBond>();
     
     /* Add ten new carbon atoms to the list of atoms */
     for(int i=0; i<10; i++)
       atoms.add(new Atom("C"));
     
     /* Create a new molecule instance from the list of atoms and bonds */
     IMolecule mol = new Molecule(atoms, bonds); 
     
     /* As the atoms are now equal to the atoms array, assert
      * the size of atoms is equal to the number of atoms in this 
      * molecule.
      */
     unit._assertEquals(mol.getAtoms().size(), atoms.size());
     unit._assertArrayEquals(mol.getAtoms().toArray(  //
		new Object[mol.getAtoms().size()]),  // Do conversion to object
		atoms.toArray(new Object[atoms.size()]));  // array for testing
     
     /* No bonds yet, still bond count should be equal to size of bonds */
     unit._assertEquals(mol.getBonds().size(), bonds.size());
     
     /* Add a new bond to the molecule */
     mol.addBond(new Bond(mol.getAtom(0), mol.getAtom(1)));
     
     /* After adding one bond, the number of bonds should be one */
     unit._assertTrue(mol.getBonds().size() == 1);
     unit._assertTrue(mol.getBondCount() == 1);
     
     /* Add yet another bond and check again the bond count */
     mol.addBond(new Bond(mol.getAtom(2), mol.getAtom(0)));
     unit._assertTrue(mol.getBonds().size() == 2);
     unit._assertTrue(mol.getBondCount() == 2);
     
     /* Assert that for any atom that is actually part of the molecule
      * the method containsAtom actually returns true.
      */
     for (IAtom atom : mol.getAtoms())
     {
		 unit._assertTrue(mol.containsAtom(atom));
	 } 
	 
	 /* Also assert, that for an atom which obviously isnt part of the
	  * of the molecule, contains returns false.
	  */
	 IAtom notInMol = new Atom("N");
	 unit._assertFalse(mol.containsAtom(notInMol));
	 notInMol = new Atom("C");  // Also check for different atom symbol
	 unit._assertFalse(mol.containsAtom(notInMol));
  }
  
  public void testJoin()
  {
	  IMolecule m1 = new Molecule();
	  IMolecule m2 = new Molecule();
	  
	  m1.addAtom(new Atom("C"));
	  m2.addAtom(new Atom("N"));
	  
	  /* The instance joined is the molecule obtained via connecting
	  * or joining the molecules m1 and m2 via their first atoms
	  */
	  IMolecule joined = m1.join(m1.getAtom(0), m2.getAtom(0),
								  m1, m2);
	  /* First, it is clear, that if m1 and m2 are not empty, then
	   * the joined molecule must contain more atoms than m1 and m2.
	   */
	  unit._assertTrue(joined.getAtomCount() > m1.getAtomCount());
	  unit._assertTrue(joined.getAtomCount() > m2.getAtomCount());
	  
	  /* Also, the atom count of joined must be the sum of the 
	   * number of atoms in m1 and m2, e.g.:
	   */							  
	  unit._assertTrue(joined.getAtomCount() == m1.getAtomCount()+
					   m2.getAtomCount());
	  
	  /* All atoms in m1 and m2 must be contained in joined: */
	  for(IAtom atm : m1.getAtoms())
	  {
		  unit._assertTrue(joined.containsAtom(atm));
	  }
	  for(IAtom atm : m2.getAtoms())
	  {
		  unit._assertTrue(joined.containsAtom(atm));
	  }
  }
  
  public void runTestCase()
  {
    testMoleculeMethods();  // Test the more or less obvious methods
    testJoin();  // Test the notoriously complex method join
  } 
}
